/*
 * Copyright (C) 2005 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.plugin.portunis.impl;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.security.KeyStoreException;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

import javax.swing.JTextArea;
import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.WorkbenchFrameListener;
import nu.zoom.swing.desktop.plugin.portunis.ApplicationPreferences;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreHandler;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreListener;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreWrapper;
import nu.zoom.swing.desktop.plugin.portunis.Utils;
import nu.zoom.swing.desktop.plugin.portunis.ZoomKeyStore;
import nu.zoom.swing.layout.VerticalPanel;

import org.ops4j.gaderian.Messages;

/**
 * A factory to produce the components that makes up a keystore frame.
 * 
 */
class KeyStoreFrame implements KeyStoreListener, WorkbenchFrameListener {

    private JPanel frameMainPanel;
    private Messages messages;
    private KeyStoreWrapper wrapper;
    private Workbench workbench;
    private KeyStoreHandler keyStoreHandler;
    private ApplicationPreferences prefs;
    private KeyStorePlugIn plugin;

    KeyStoreFrame(KeyStorePlugIn plugin, KeyStoreHandler keyStoreHandler,
            ApplicationPreferences prefs, KeyStoreWrapper wrapper,
            Messages messages, Workbench workbench) {
        super();
        this.plugin = plugin;
        this.wrapper = wrapper;
        this.messages = messages;
        this.workbench = workbench;
        this.keyStoreHandler = keyStoreHandler;
        this.prefs = prefs;
        frameMainPanel = new JPanel(new BorderLayout());
    }

    WorkbenchFrame getWorkbenchFrame() throws KeyStoreException {
        String title = (wrapper.getFile() == null) ? messages.getMessage("keystore.noname") : wrapper.getFile().getAbsolutePath();
        String prefsKey = "keystore." + Integer.toHexString(title.hashCode());

        JComponent comp = getFrameContent();
        frameMainPanel.add(comp, BorderLayout.CENTER);
        JMenuBar menuBar = getFrameMenubar();
        WorkbenchFrame frame = workbench.createWorkbenchFrame(prefsKey,
                frameMainPanel, menuBar, true, true);
        frame.setTitle(title);
        frame.setFrameIcon(Utils.getIconFromMessages(messages,
                "keystore.load.loaded.icon"));
        frame.setVisible(true);
        wrapper.getKeyStore().addKeyStoreListener(this);
        return frame;
    }

    private JComponent getFrameContent() throws KeyStoreException {
        VerticalPanel keystorePanel = new VerticalPanel();

        String filename = (wrapper.getFile() != null) ? wrapper.getFile().getAbsolutePath() : messages.getMessage("keystore.noname");
        keystorePanel.addRow(messages.getMessage("keystore.display.file"),
                filename);

        ZoomKeyStore store = wrapper.getKeyStore();
        keystorePanel.addRow(messages.getMessage("keystore.display.type"),
                store.getType());

        Enumeration aliases = wrapper.getKeyStore().aliases();
        ArrayList<String> certAliases = new ArrayList<String>();
        ArrayList<String> keyAliases = new ArrayList<String>();
        ArrayList<String> unknownAliases = new ArrayList<String>();
        while (aliases.hasMoreElements()) {
            String alias = (String) aliases.nextElement();
            if (store.isCertificateEntry(alias)) {
                certAliases.add(alias);
            } else if (store.isKeyEntry(alias)) {
                keyAliases.add(alias);
            } else {
                unknownAliases.add(alias);
            }
        }

        keystorePanel.addRow(messages.getMessage("keystore.display.numkeys"),
                "" + keyAliases.size());

        keystorePanel.addRow(messages.getMessage("keystore.display.numcerts"),
                "" + certAliases.size());

        if (unknownAliases.size() > 0) {
            keystorePanel.addRow(messages.getMessage("keystore.display.numunknown"), "" + unknownAliases.size());
        }

        keystorePanel.addRow(messages.getMessage("keystore.display.provider"),
                store.getProvider().getName());

        JTextArea providerInfoArea = new JTextArea();
        providerInfoArea.setLineWrap(true);
        providerInfoArea.setColumns(40);
        providerInfoArea.setText(store.getProvider().getInfo());
        providerInfoArea.setEditable(false);
        keystorePanel.addRow(messages.getMessage("keystore.display.providerinfo"), providerInfoArea);

        if ((keyAliases.size() + certAliases.size()) > 0) {
            // Do tabbed display
            JTabbedPane tabPane = new JTabbedPane(JTabbedPane.NORTH);
            tabPane.addTab(messages.getMessage("keystore.display.tab"),
                    Utils.getIconFromMessages(messages,
                    "keystore.load.loaded.icon"), createScrollPane(
                    keystorePanel), messages.getMessage("keystore.display.tab.tooltip"));

            if (certAliases.size() > 0) {
                tabPane.addTab(
                        messages.getMessage("keystore.display.certtab"),
                        Utils.getIconFromMessages(messages,
                        "keystore.display.cert.icon"),
                        new DisplayCertificates(workbench,
                        store, certAliases, messages),
                        messages.getMessage("keystore.display.certtab.tooltip"));
            }
            if (keyAliases.size() > 0) {
                tabPane.addTab(messages.getMessage("keystore.display.keytab"),
                        Utils.getIconFromMessages(messages,
                        "keystore.display.key.icon"), createScrollPane(
                        new DisplayKeys(workbench, store, keyAliases,
                        messages)), messages.getMessage("keystore.display.keytab.tooltip"));
            }

            return tabPane;
        } else {
            return new JScrollPane(keystorePanel);
        }
    }

    private JScrollPane createScrollPane(final Component component) {
        JScrollPane p = new JScrollPane(component);
        p.getVerticalScrollBar().setUnitIncrement(16);
        return p;
    }

    private JMenuBar getFrameMenubar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu keyStoreMenu = new JMenu(messages.getMessage("keystore.menu"));

        // Build actions
        // Save
        keyStoreMenu.add(new SaveKeyStoreAction(plugin, keyStoreHandler,
                workbench, prefs, messages, wrapper, false));
        // SaveAs
        keyStoreMenu.add(new SaveKeyStoreAction(plugin, keyStoreHandler,
                workbench, prefs, messages, wrapper, true));
        // Import cert
        keyStoreMenu.add(new ImportCertificateAction(prefs, workbench,
                messages, wrapper.getKeyStore()));

        menuBar.add(keyStoreMenu);
        return menuBar;
    }

    private void reconstructFrameContent() {
        try {
            frameMainPanel.removeAll();
            JComponent content = getFrameContent();
            frameMainPanel.add(content, BorderLayout.CENTER);
        } catch (KeyStoreException e) {
            workbench.getErrorReporter().reportError(e);
            frameMainPanel.add(new JLabel(e.getLocalizedMessage()),
                    BorderLayout.CENTER);
        }
        frameMainPanel.revalidate();
    }

    @Override
    public void keyStoreChanged(ZoomKeyStore store) {
        if (!EventQueue.isDispatchThread()) {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    reconstructFrameContent();
                }
            });
        } else {
            reconstructFrameContent();
        }
    }

    @Override
    public void frameClosed(WorkbenchFrame frame) {
        if (wrapper != null) {
            if (wrapper.getKeyStore() != null) {
                wrapper.getKeyStore().removeKeyStoreListener(this);
            }
        }
    }

    @Override
    public void frameWillDispose(WorkbenchFrame frame) {
    }

    @Override
    public void frameDetached(WorkbenchFrame frame) {
    }

    @Override
    public void frameAttached(WorkbenchFrame frame) {
    }
}
